bitkeeper revision 1.770 (4049e6c8Y4j_un8mTZVBzW2v2v9zjQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sat, 6 Mar 2004 14:57:12 +0000 (14:57 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sat, 6 Mar 2004 14:57:12 +0000 (14:57 +0000)
console.c:
  new file
Many files:
  Redirect to DOM0 linux to new serial io interface. Deprecated HYPERVISOR_console_write.
.del-printk.c~67ddc78b3f262afa:
  Delete: xenolinux-2.4.25-sparse/kernel/printk.c
.del-console.c~cc66a22964db9adc:
  Delete: xen/common/console.c
keyboard.c:
  Rename: xen/drivers/char/xen_kbd.c -> xen/drivers/char/keyboard.c

17 files changed:
.rootkeys
xen/arch/i386/entry.S
xen/common/console.c [deleted file]
xen/common/dom0_ops.c
xen/common/domain.c
xen/common/kernel.c
xen/common/keyhandler.c
xen/drivers/char/console.c [new file with mode: 0644]
xen/drivers/char/keyboard.c [new file with mode: 0644]
xen/drivers/char/xen_kbd.c [deleted file]
xen/include/hypervisor-ifs/hypervisor-if.h
xen/include/xeno/console.h
xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c
xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h
xenolinux-2.4.25-sparse/include/asm-xeno/processor.h
xenolinux-2.4.25-sparse/kernel/panic.c
xenolinux-2.4.25-sparse/kernel/printk.c [deleted file]

index c7c8cc401065d56998f30ecf83ebe9019043081d..71702d606de23e3ab2df205b05c6548eb98e69f2 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
 3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c
 3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c
-3fb10d07GscSWPKxBqpvNfU-dYfa0g xen/common/console.c
 4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
 3fa152581E5KhrAtqZef2Sr5NKTz4w xen/common/debug.c
 3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
 3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
 3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
+4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c
+3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/keyboard.c
 3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
-3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
 3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile
 3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c
 3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h
 401c0592pLrp_aCbQRo9GXiYQQaVVA xenolinux-2.4.25-sparse/include/linux/timer.h
 3e5a4e68W_hpMlM3u_-QOKMp3gzcwQ xenolinux-2.4.25-sparse/init/do_mounts.c
 3e5a4e68TJJavrunYwTAnLRSBxSYqQ xenolinux-2.4.25-sparse/kernel/panic.c
-3f1056a9LXNTgSzITNh1mb-MIKV1Ng xenolinux-2.4.25-sparse/kernel/printk.c
 3f9d4b44247udoqWEgFkaHiWv6Uvyg xenolinux-2.4.25-sparse/kernel/time.c
 401c059bjLBFYHRD4Py2uM3eA1D4zQ xenolinux-2.4.25-sparse/kernel/timer.c
 3eba8f878XjouY21EkQBXwYBsPsipQ xenolinux-2.4.25-sparse/lndir-rel
index c1c57ac11d796cb1d274269c11299945985f4e45..bc0fc732a8fe272f716f0f129549de90ace0523d 100644 (file)
@@ -727,6 +727,7 @@ ENTRY(hypervisor_call_table)
         .long SYMBOL_NAME(do_set_timer_op)       /* 20 */
         .long SYMBOL_NAME(do_event_channel_op)
         .long SYMBOL_NAME(do_xen_version)
+        .long SYMBOL_NAME(do_serial_io)
         .rept NR_syscalls-((.-hypervisor_call_table)/4)
         .long SYMBOL_NAME(do_ni_syscall)
         .endr
diff --git a/xen/common/console.c b/xen/common/console.c
deleted file mode 100644 (file)
index d52a8cf..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * console.c
- *
- * read domain console output buffer ring in Xen 
- *
- */
-
-#include <xeno/console.h>
-#include <asm-i386/uaccess.h>
-
-console_ring_t console_ring = {
-    .len = 0
-};
-
-long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
-{
-    unsigned int len;
-    
-    len = (console_ring.len < count) ? console_ring.len : count;
-    
-    if ( copy_to_user((char *)str, console_ring.buf, len) )
-        return -EFAULT;
-
-    if ( cmd & CONSOLE_RING_CLEAR ) {
-       console_ring.len = 0;
-    }
-    
-    return len;
-}
index 45f11108cce33ccd334bd24b2597a67dd01f9fbb..11e755e65dc7a4ccf51b9ee51cc332a6350b7612 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/msr.h>
 #include <asm/pdb.h>
 #include <xeno/trace.h>
+#include <xeno/console.h>
 
 extern unsigned int alloc_new_dom_mem(struct task_struct *, unsigned int);
 
@@ -443,8 +444,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     
     case DOM0_READCONSOLE:
     {
-       extern long read_console_ring(unsigned long, 
-                                      unsigned int, unsigned int);
         ret = read_console_ring(op->u.readconsole.str, 
                                op->u.readconsole.count,
                                op->u.readconsole.cmd); 
index 8186248dc827ac80fb3a89f7e965b43a4f87df02..d226c52d5ffbfe61b4dcb18d059a68384a42b06c 100644 (file)
@@ -806,9 +806,8 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
     }
     *dst = '\0';
 
-    /* HACK: Give up the VGA console iff the Xenolinux DOM0 wants it. */
-    if ( strstr(cmdline, "tty0") != NULL )
-        vgacon_enabled = 0;
+    /* NB: Give up the VGA console iff the Xenolinux DOM0 wants it. */
+    console_endboot(strstr(cmdline, "tty0") != NULL);
 
     /* Reinstate the caller's page tables. */
     write_cr3_counted(pagetable_val(current->mm.pagetable));
index a906786c428a9e9521830259c459de0e8c376828..055316e7a788bbc5ff5aa8ff2f7e5e44f1d791fd 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <stdarg.h>
+#include <xeno/config.h>
 #include <xeno/lib.h>
 #include <xeno/errno.h>
 #include <xeno/spinlock.h>
 
 kmem_cache_t *task_struct_cachep;
 
-static int xpos, ypos;
-static unsigned char *video = __va(0xB8000);
-
-int sercon_handle = -1;
-int vgacon_enabled = 0;
-
-spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
-
 struct e820entry {
     unsigned long addr_lo, addr_hi;        /* start of memory segment */
     unsigned long size_lo, size_hi;        /* size of memory segment */
     unsigned long type;                    /* type of memory segment */
 };
 
-static void init_vga(void);
 void start_of_day(void);
 
 /* opt_console: comma-separated list of console outputs. */
@@ -108,7 +100,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
     struct task_struct *new_dom;
     dom0_createdomain_t dom0_params;
     unsigned long max_page;
-    unsigned char *cmdline, *p;
+    unsigned char *cmdline;
     module_t *mod;
     void *heap_start;
     int i;
@@ -162,19 +154,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
     /* We initialise the serial devices very early so we can get debugging. */
     serial_init_stage1();
 
-    /* Where should console output go? */
-    for ( p = opt_console; p != NULL; p = strchr(p, ',') )
-    {
-        if ( *p == ',' )
-            p++;
-        if ( strncmp(p, "com", 3) == 0 )
-            sercon_handle = parse_serial_handle(p);
-        else if ( strncmp(p, "vga", 3) == 0 )
-            vgacon_enabled = 1;
-    }
-
-    /* Set up VGA console output, if it was enabled. */
-    init_vga();
+    init_console();
 
     /* HELLO WORLD --- start-of-day banner text. */
     printk(XEN_BANNER);
@@ -184,6 +164,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
            XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
            XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
            XEN_COMPILER, XEN_COMPILE_DATE);
+    set_printk_prefix("(XEN) ");
 
     if ( opt_ser_baud != 0 )
         printk("**WARNING**: Xen option 'ser_baud=' is deprecated! "
@@ -266,294 +247,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
     startup_cpu_idle_loop();
 }
 
-
-/*********************************
- * Various console code follows...
- */
-
-/* VGA text (mode 3) definitions. */
-#define COLUMNS            80
-#define LINES      25
-#define ATTRIBUTE    7
-
-/* Clear the screen and initialize VIDEO, XPOS and YPOS.  */
-static void cls(void)
-{
-    memset(video, 0, COLUMNS * LINES * 2);
-    xpos = ypos = 0;
-    outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
-}
-
-static int detect_video(void *video_base)
-{
-    volatile u16 *p = (volatile u16 *)video_base;
-    u16 saved1 = p[0], saved2 = p[1];
-    int video_found = 1;
-
-    p[0] = 0xAA55;
-    p[1] = 0x55AA;
-    if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
-        video_found = 0;
-
-    p[0] = 0x55AA;
-    p[1] = 0xAA55;
-    if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
-        video_found = 0;
-
-    p[0] = saved1;
-    p[1] = saved2;
-
-    return video_found;
-}
-
-static int detect_vga(void)
-{
-    /*
-     * Look at a number of well-known locations. Even if video is not at
-     * 0xB8000 right now, it will appear there when we set up text mode 3.
-     * 
-     * We assume if there is any sign of a video adaptor then it is at least
-     * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
-     * 
-     * These checks are basically to detect headless server boxes.
-     */
-    return (detect_video(__va(0xA0000)) || 
-            detect_video(__va(0xB0000)) || 
-            detect_video(__va(0xB8000)));
-}
-
-/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
-static void init_vga(void)
-{
-    /* The following VGA state was saved from a chip in text mode 3. */
-    static unsigned char regs[] = {
-        /* Sequencer registers */
-        0x03, 0x00, 0x03, 0x00, 0x02,
-        /* CRTC registers */
-        0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
-        0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
-        0xb9, 0xa3, 0xff,
-        /* Graphic registers */
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
-        /* Attribute registers */
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
-        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
-    };
-
-    int i, j = 0;
-    volatile unsigned char tmp;
-
-    if ( !vgacon_enabled )
-        return;
-
-    if ( !detect_vga() )
-    {
-        printk("No VGA adaptor detected!\n");
-        vgacon_enabled = 0;
-        return;
-    }
-
-    tmp = inb(0x3da);
-    outb(0x00, 0x3c0);
-    
-    for ( i = 0; i < 5;  i++ )
-        outw((regs[j++] << 8) | i, 0x3c4);
-    
-    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
-    outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
-    
-    for ( i = 0; i < 25; i++ ) 
-        outw((regs[j++] << 8) | i, 0x3d4);
-    
-    for ( i = 0; i < 9;  i++ )
-        outw((regs[j++] << 8) | i, 0x3ce);
-    
-    for ( i = 0; i < 21; i++ )
-    {
-        tmp = inb(0x3da);
-        outb(i, 0x3c0); 
-        outb(regs[j++], 0x3c0);
-    }
-    
-    tmp = inb(0x3da);
-    outb(0x20, 0x3c0);
-
-    cls();
-}
-
-
-static void put_newline(void)
-{
-    xpos = 0;
-    ypos++;
-
-    if (ypos >= LINES)
-    {
-        static char zeroarr[2*COLUMNS] = { 0 };
-        ypos = LINES-1;
-        memcpy((char*)video, 
-               (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
-        memcpy((char*)video + (LINES-1)*2*COLUMNS, 
-               zeroarr, 2*COLUMNS);
-    }
-}
-
-
-static void putchar_console(int c)
-{
-    if ( !vgacon_enabled )
-        return;
-
-    if ( c == '\n' )
-    {
-        put_newline();
-    }
-    else
-    {
-        video[(xpos + ypos * COLUMNS) * 2]     = c & 0xFF;
-        video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
-        if ( ++xpos >= COLUMNS )
-            put_newline();
-    }
-}
-
-
-void putchar_console_ring(int c)
-{
-    if ( console_ring.len < CONSOLE_RING_SIZE )
-        console_ring.buf[console_ring.len++] = (char)c;
-}
-
-
-static inline void __putstr(const char *str)
-{
-    int c;
-    serial_puts(sercon_handle, str);
-    while ( (c = *str++) != '\0' )
-    {
-        putchar_console(c);
-        putchar_console_ring(c);
-    }
-}
-
-
-void printf(const char *fmt, ...)
-{
-    va_list args;
-    char buf[128];
-    const char *p = fmt;
-    unsigned long flags;
-
-    /*
-     * If the format string contains '%' descriptors then we have to parse it 
-     * before printing it. We parse it into a fixed-length buffer. Long 
-     * strings should therefore _not_ contain '%' characters!
-     */
-    if ( strchr(fmt, '%') != NULL )
-    {
-        va_start(args, fmt);
-        (void)vsnprintf(buf, sizeof(buf), fmt, args);
-        va_end(args);        
-        p = buf; 
-    }
-
-    spin_lock_irqsave(&console_lock, flags);
-    __putstr(p);
-    spin_unlock_irqrestore(&console_lock, flags);
-}
-
-
-long do_console_write(char *str, unsigned int count)
-{
-#define SIZEOF_BUF 256
-    unsigned char safe_str[SIZEOF_BUF+1];
-    unsigned char single_line[SIZEOF_BUF+2];
-    unsigned char line_header[30];
-    unsigned char *p;
-    unsigned char  c;
-    unsigned long flags;
-    int            j;
-    
-    if ( count == 0 )
-        return 0;
-
-    if ( count > SIZEOF_BUF ) 
-        count = SIZEOF_BUF;
-    
-    if ( copy_from_user(safe_str, str, count) )
-        return -EFAULT;
-    safe_str[count] = '\0';
-    
-    sprintf(line_header, "DOM%llu: ", current->domain);
-    
-    p = safe_str;
-    while ( *p != '\0' )
-    {
-        j = 0;
-
-        while ( (c = *p++) != '\0' )
-        {
-            if ( c == '\n' )
-                break;
-            if ( (c < 32) || (c > 126) )
-                continue;
-            single_line[j++] = c;
-        }
-
-        single_line[j++] = '\n';
-        single_line[j++] = '\0';
-
-        spin_lock_irqsave(&console_lock, flags);
-        __putstr(line_header);
-        __putstr(single_line);
-        spin_unlock_irqrestore(&console_lock, flags);
-    }
-
-    return 0;
-}
-
-
-/*********************************
- * Debugging/tracing/error-report.
- */
-
-void panic(const char *fmt, ...)
-{
-    va_list args;
-    char buf[128];
-    unsigned long flags;
-    extern void machine_restart(char *);
-    
-    va_start(args, fmt);
-    (void)vsnprintf(buf, sizeof(buf), fmt, args);
-    va_end(args);
-    
-    /* Spit out multiline message in one go. */
-    spin_lock_irqsave(&console_lock, flags);
-    __putstr("\n****************************************\n");
-    __putstr(buf);
-    __putstr("Aieee! CPU");
-    sprintf(buf, "%d", smp_processor_id());
-    __putstr(buf);
-    __putstr(" is toast...\n");
-    __putstr("****************************************\n\n");
-    __putstr("Reboot in five seconds...\n");
-    spin_unlock_irqrestore(&console_lock, flags);
-
-    mdelay(5000);
-    machine_restart(0);
-}
-
-
-void __out_of_line_bug(int line)
-{
-    printk("kernel BUG in header file at line %d\n", line);
-    BUG();
-    for ( ; ; ) continue;
-}
-
-
-/*********************************
+/*
  * Simple syscalls.
  */
 
index a71aec760edee0729769f1c513981f4e59a4c1ef..32786fdfd12d227a6bb26f63921ed0fa4ddd9263 100644 (file)
@@ -42,13 +42,6 @@ key_handler *get_key_handler(u_char key)
     return key_table[key].handler; 
 }
 
-static void serial_rx(unsigned char c, struct pt_regs *regs)
-{
-    key_handler *handler;
-    if ( (handler = get_key_handler(c)) != NULL )
-        (*handler)(c, NULL, regs);
-}
-
 static void show_handlers(u_char key, void *dev_id, struct pt_regs *regs) 
 {
     int i; 
@@ -160,6 +153,4 @@ void initialize_keytable(void)
     add_key_handler('m', reaudit_pages, "re-audit pages");
     add_key_handler('M', audit_all_pages, "audit all pages");
 #endif
-
-    serial_set_rx_handler(sercon_handle, serial_rx);
 }
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
new file mode 100644 (file)
index 0000000..6728a32
--- /dev/null
@@ -0,0 +1,498 @@
+/******************************************************************************
+ * console.c
+ * 
+ * Emergency console I/O for Xen and the domain-0 guest OS.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser.
+ */
+
+#include <stdarg.h>
+#include <xeno/config.h>
+#include <xeno/lib.h>
+#include <xeno/errno.h>
+#include <xeno/event.h>
+#include <xeno/spinlock.h>
+#include <xeno/console.h>
+#include <xeno/serial.h>
+#include <xeno/keyhandler.h>
+#include <asm/uaccess.h>
+
+static int xpos, ypos;
+static unsigned char *video = __va(0xB8000);
+
+#define CONSOLE_RING_SIZE 16392
+typedef struct console_ring_st
+{
+    char buf[CONSOLE_RING_SIZE];
+    unsigned int len;
+} console_ring_t;
+static console_ring_t console_ring;
+
+static char printk_prefix[16] = "";
+
+static int sercon_handle = -1;
+static int vgacon_enabled = 0;
+
+spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * *******************************************************
+ * *************** OUTPUT TO VGA CONSOLE *****************
+ * *******************************************************
+ */
+
+/* VGA text (mode 3) definitions. */
+#define COLUMNS            80
+#define LINES      25
+#define ATTRIBUTE    7
+
+/* Clear the screen and initialize VIDEO, XPOS and YPOS.  */
+static void cls(void)
+{
+    memset(video, 0, COLUMNS * LINES * 2);
+    xpos = ypos = 0;
+    outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
+}
+
+static int detect_video(void *video_base)
+{
+    volatile u16 *p = (volatile u16 *)video_base;
+    u16 saved1 = p[0], saved2 = p[1];
+    int video_found = 1;
+
+    p[0] = 0xAA55;
+    p[1] = 0x55AA;
+    if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
+        video_found = 0;
+
+    p[0] = 0x55AA;
+    p[1] = 0xAA55;
+    if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
+        video_found = 0;
+
+    p[0] = saved1;
+    p[1] = saved2;
+
+    return video_found;
+}
+
+static int detect_vga(void)
+{
+    /*
+     * Look at a number of well-known locations. Even if video is not at
+     * 0xB8000 right now, it will appear there when we set up text mode 3.
+     * 
+     * We assume if there is any sign of a video adaptor then it is at least
+     * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
+     * 
+     * These checks are basically to detect headless server boxes.
+     */
+    return (detect_video(__va(0xA0000)) || 
+            detect_video(__va(0xB0000)) || 
+            detect_video(__va(0xB8000)));
+}
+
+/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
+static void init_vga(void)
+{
+    /* The following VGA state was saved from a chip in text mode 3. */
+    static unsigned char regs[] = {
+        /* Sequencer registers */
+        0x03, 0x00, 0x03, 0x00, 0x02,
+        /* CRTC registers */
+        0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
+        0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
+        0xb9, 0xa3, 0xff,
+        /* Graphic registers */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
+        /* Attribute registers */
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
+        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
+    };
+
+    int i, j = 0;
+    volatile unsigned char tmp;
+
+    if ( !vgacon_enabled )
+        return;
+
+    if ( !detect_vga() )
+    {
+        printk("No VGA adaptor detected!\n");
+        vgacon_enabled = 0;
+        return;
+    }
+
+    tmp = inb(0x3da);
+    outb(0x00, 0x3c0);
+    
+    for ( i = 0; i < 5;  i++ )
+        outw((regs[j++] << 8) | i, 0x3c4);
+    
+    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
+    outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
+    
+    for ( i = 0; i < 25; i++ ) 
+        outw((regs[j++] << 8) | i, 0x3d4);
+    
+    for ( i = 0; i < 9;  i++ )
+        outw((regs[j++] << 8) | i, 0x3ce);
+    
+    for ( i = 0; i < 21; i++ )
+    {
+        tmp = inb(0x3da);
+        outb(i, 0x3c0); 
+        outb(regs[j++], 0x3c0);
+    }
+    
+    tmp = inb(0x3da);
+    outb(0x20, 0x3c0);
+
+    cls();
+}
+
+static void put_newline(void)
+{
+    xpos = 0;
+    ypos++;
+
+    if (ypos >= LINES)
+    {
+        static char zeroarr[2*COLUMNS] = { 0 };
+        ypos = LINES-1;
+        memcpy((char*)video, 
+               (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
+        memcpy((char*)video + (LINES-1)*2*COLUMNS, 
+               zeroarr, 2*COLUMNS);
+    }
+}
+
+static void putchar_console(int c)
+{
+    if ( !vgacon_enabled )
+        return;
+
+    if ( c == '\n' )
+    {
+        put_newline();
+    }
+    else
+    {
+        video[(xpos + ypos * COLUMNS) * 2]     = c & 0xFF;
+        video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
+        if ( ++xpos >= COLUMNS )
+            put_newline();
+    }
+}
+
+
+/*
+ * ********************************************************
+ * *************** ACCESS TO CONSOLE RING *****************
+ * ********************************************************
+ */
+
+static void putchar_console_ring(int c)
+{
+    if ( console_ring.len < CONSOLE_RING_SIZE )
+        console_ring.buf[console_ring.len++] = (char)c;
+}
+
+long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
+{
+    unsigned int len;
+    
+    len = (console_ring.len < count) ? console_ring.len : count;
+    
+    if ( copy_to_user((char *)str, console_ring.buf, len) )
+        return -EFAULT;
+
+    if ( cmd & CONSOLE_RING_CLEAR )
+       console_ring.len = 0;
+    
+    return len;
+}
+
+
+/*
+ * *******************************************************
+ * *************** ACCESS TO SERIAL LINE *****************
+ * *******************************************************
+ */
+
+/* Characters received over the serial line are buffered for domain 0. */
+#define SERIAL_RX_SIZE 128
+#define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
+static char serial_rx_ring[SERIAL_RX_SIZE];
+static unsigned int serial_rx_cons, serial_rx_prod;
+
+/* CTRL-a switches input direction between Xen and DOM0. */
+#define CTRL_A 0x01
+
+static void serial_rx(unsigned char c, struct pt_regs *regs)
+{
+    key_handler *handler;
+    unsigned long cpu_mask;
+    struct task_struct *p;
+    static char *input_str[2] = { "DOM0", "Xen" };
+    static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
+
+    if ( c == CTRL_A )
+    {
+        xen_rx = !xen_rx;
+        printk("*** Serial input -> %s "
+               "(type 'CTRL-a' to switch input to %s).\n",
+               input_str[xen_rx], input_str[!xen_rx]);
+    }
+    else if ( xen_rx )
+    {
+        if ( (handler = get_key_handler(c)) != NULL )
+            (*handler)(c, NULL, regs);
+    }
+    else if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
+    {
+        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod)] = c;
+        if ( serial_rx_prod++ == serial_rx_cons )
+        {
+            p = find_domain_by_id(0); /* only DOM0 reads the serial buffer */
+            cpu_mask = mark_guest_event(p, _EVENT_CONSOLE);
+            guest_event_notify(cpu_mask);
+            put_task_struct(p);
+        }
+    }
+}
+
+long do_serial_io(int cmd, int count, char *buffer)
+{
+    char *kbuf;
+    long  rc;
+
+    /* Only domain-0 may access the emrgency console. */
+    if ( current->domain != 0 )
+        return -EPERM;
+
+    switch ( cmd )
+    {
+    case SERIALIO_write:
+        if ( count > (PAGE_SIZE-1) )
+            count = PAGE_SIZE-1;
+        if ( (kbuf = (char *)get_free_page(GFP_KERNEL)) == NULL )
+            return -ENOMEM;
+        kbuf[count] = '\0';
+        rc = count;
+        if ( copy_from_user(kbuf, buffer, count) )
+            rc = -EFAULT;
+        else
+            serial_puts(sercon_handle, kbuf);
+        free_page((unsigned long)kbuf);
+        break;
+    case SERIALIO_read:
+        rc = 0;
+        while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
+        {
+            if ( put_user(serial_rx_ring[SERIAL_RX_MASK(serial_rx_cons)],
+                          &buffer[rc]) )
+            {
+                rc = -EFAULT;
+                break;
+            }
+            rc++;
+            serial_rx_cons++;
+        }
+        break;
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    return rc;
+}
+
+
+/*
+ * *****************************************************
+ * *************** GENERIC CONSOLE I/O *****************
+ * *****************************************************
+ */
+
+static inline void __putstr(const char *str)
+{
+    int c;
+    serial_puts(sercon_handle, str);
+    while ( (c = *str++) != '\0' )
+    {
+        putchar_console(c);
+        putchar_console_ring(c);
+    }
+}
+
+void printf(const char *fmt, ...)
+{
+    static char   buf[1024];
+    static int    start_of_line = 1;
+
+    va_list       args;
+    char         *p, *q;
+    unsigned long flags;
+
+    spin_lock_irqsave(&console_lock, flags);
+
+    va_start(args, fmt);
+    (void)vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);        
+
+    p = buf;
+    while ( (q = strchr(p, '\n')) != NULL )
+    {
+        *q = '\0';
+        if ( start_of_line )
+            __putstr(printk_prefix);
+        __putstr(p);
+        __putstr("\n");
+        start_of_line = 1;
+        p = q + 1;
+    }
+
+    if ( *p != '\0' )
+    {
+        if ( start_of_line )
+            __putstr(printk_prefix);
+        __putstr(p);
+        start_of_line = 0;
+    }
+
+    spin_unlock_irqrestore(&console_lock, flags);
+}
+
+void set_printk_prefix(const char *prefix)
+{
+    strcpy(printk_prefix, prefix);
+}
+
+/*
+ * This hypercall is deprecated. Only permit its use in debug environments.
+ */
+long do_console_write(char *str, unsigned int count)
+{
+#ifndef NDEBUG
+#define SIZEOF_BUF 256
+    unsigned char safe_str[SIZEOF_BUF+1];
+    unsigned char single_line[SIZEOF_BUF+2];
+    unsigned char line_header[30];
+    unsigned char *p;
+    unsigned char  c;
+    unsigned long flags;
+    int            j;
+    
+    if ( count == 0 )
+        return 0;
+
+    if ( count > SIZEOF_BUF ) 
+        count = SIZEOF_BUF;
+    
+    if ( copy_from_user(safe_str, str, count) )
+        return -EFAULT;
+    safe_str[count] = '\0';
+    
+    sprintf(line_header, "DOM%llu: ", current->domain);
+    
+    p = safe_str;
+    while ( *p != '\0' )
+    {
+        j = 0;
+
+        while ( (c = *p++) != '\0' )
+        {
+            if ( c == '\n' )
+                break;
+            if ( (c < 32) || (c > 126) )
+                continue;
+            single_line[j++] = c;
+        }
+
+        single_line[j++] = '\n';
+        single_line[j++] = '\0';
+
+        spin_lock_irqsave(&console_lock, flags);
+        __putstr(line_header);
+        __putstr(single_line);
+        spin_unlock_irqrestore(&console_lock, flags);
+    }
+
+    return 0;
+#else
+    return -ENOSYS;
+#endif
+}
+
+void init_console(void)
+{
+    extern unsigned char opt_console[];
+    unsigned char *p;
+
+    /* Where should console output go? */
+    for ( p = opt_console; p != NULL; p = strchr(p, ',') )
+    {
+        if ( *p == ',' )
+            p++;
+        if ( strncmp(p, "com", 3) == 0 )
+            sercon_handle = parse_serial_handle(p);
+        else if ( strncmp(p, "vga", 3) == 0 )
+            vgacon_enabled = 1;
+    }
+
+    init_vga();
+
+    serial_set_rx_handler(sercon_handle, serial_rx);
+}
+
+void console_endboot(int disable_vga)
+{
+    if ( disable_vga )
+        vgacon_enabled = 0;
+    /* Serial input is directed to DOM0 by default. */
+    serial_rx(CTRL_A, NULL);
+}
+
+
+/*
+ * **************************************************************
+ * *************** Debugging/tracing/error-report ***************
+ * **************************************************************
+ */
+
+void panic(const char *fmt, ...)
+{
+    va_list args;
+    char buf[128];
+    unsigned long flags;
+    extern void machine_restart(char *);
+    
+    va_start(args, fmt);
+    (void)vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+    
+    /* Spit out multiline message in one go. */
+    spin_lock_irqsave(&console_lock, flags);
+    __putstr("\n****************************************\n");
+    __putstr(buf);
+    __putstr("Aieee! CPU");
+    sprintf(buf, "%d", smp_processor_id());
+    __putstr(buf);
+    __putstr(" is toast...\n");
+    __putstr("****************************************\n\n");
+    __putstr("Reboot in five seconds...\n");
+    spin_unlock_irqrestore(&console_lock, flags);
+
+    mdelay(5000);
+    machine_restart(0);
+}
+
+
+void __out_of_line_bug(int line)
+{
+    printk("kernel BUG in header file at line %d\n", line);
+    BUG();
+    for ( ; ; ) ;
+}
diff --git a/xen/drivers/char/keyboard.c b/xen/drivers/char/keyboard.c
new file mode 100644 (file)
index 0000000..40fc68c
--- /dev/null
@@ -0,0 +1,266 @@
+/******************************************************************************
+ * keyboard.c
+ * 
+ * Driver for IBM PC AT- and PS/2-compatible keyboards.
+ * 
+ * This file contains portions of code from Linux.
+ */
+
+#include <asm-i386/io.h>
+#include <asm-i386/irq.h>
+#include <xeno/sched.h>
+#include <xeno/keyhandler.h>  
+#include <hypervisor-ifs/kbd.h>
+#include <xeno/event.h>
+#include <xeno/console.h>
+
+/* Hash-defines torn from <linux/pc_keyb.h> and <asm/keyboard.h> */
+
+#define KBD_STATUS_REG      0x64 /* Status register (R) */
+#define KBD_CNTL_REG        0x64 /* Controller command register (W) */
+#define KBD_DATA_REG        0x60 /* Keyboard data register (R/W) */
+
+/* register status bits */
+#define KBD_STAT_OBF        0x01 /* Keyboard output buffer full */
+#define KBD_STAT_IBF        0x02 /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST    0x04 /* Self test successful */
+#define KBD_STAT_CMD        0x08 /* Last write was a command write (0=data) */
+
+#define KBD_STAT_UNLOCKED    0x10 /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF   0x20 /* Mouse output buffer full */
+#define KBD_STAT_GTO        0x40 /* General receive/xmit timeout */
+#define KBD_STAT_PERR       0x80 /* Parity error */
+
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+
+#define KEYBOARD_IRQ  1
+#define AUX_IRQ      12
+
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+#ifdef CONFIG_XEN_ATTENTION_KEY
+
+static int xen_attention_key_down = 0;
+#define XEN_ATTENTION_KEY 0x46 /* Scroll Lock */
+#define KBD_SCANCODE_KEYUP_MASK 0x80
+
+/* Simple scancode-to-key mappings for internal Xen use. */
+
+static unsigned char keymap_normal[] =
+{
+    0 , 0 ,'1','2', '3','4','5','6',    '7','8','9','0', '-','=','\b','\t',
+    'q','w','e','r', 't','y','u','i',    'o','p','[',']','\r', 0 ,'a','s',
+    'd','f','g','h', 'j','k','l',';',   '\'','`', 0 ,'#', 'z','x','c','v',
+    'b','n','m',',', '.','/', 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 ,'\\', 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 
+};
+
+static unsigned char keymap_shift[] =
+{
+    0 , 0 ,'!','"', '#','$','%','^',    '&','*','(',')', '_','+','\b','\t',
+    'Q','W','E','R', 'T','Y','U','I',    'O','P','{','}','\r', 0 ,'A','S',
+    'D','F','G','H', 'J','K','L',':',    '@', 0 , 0 ,'~', 'Z','X','C','V',
+    'B','N','M','<', '>','?', 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 ,'|', 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
+    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 
+};
+
+
+static int keyboard_shift = 0;
+
+static unsigned char convert_scancode (unsigned char scancode)
+{
+    unsigned char value = 0;
+
+    switch ( scancode ) 
+    {
+
+    case 0xaa: /* shift (left) UP */
+    case 0xb6: /* shift (right) UP */
+       keyboard_shift = 0;
+       break;
+
+    case 0x2a: /* shift (left) DOWN */
+    case 0x36: /* shift (right) DOWN */
+       keyboard_shift = 1;
+       break;
+
+    default:
+        /* Only process key-up events */
+        if(!(scancode & KBD_SCANCODE_KEYUP_MASK)) 
+            break; 
+       scancode = scancode & ~KBD_SCANCODE_KEYUP_MASK; 
+       if (keyboard_shift)
+           value = keymap_shift[scancode];
+       else
+           value = keymap_normal[scancode];
+        break;
+    }
+
+    return value;
+}
+
+#endif /* CONFIG_XEN_ATTENTION_KEY */
+
+
+/* We store kbd events awaiting receive by a guest OS in a ring buffer. */
+#define KBD_RING_SIZE 64 
+static int kbd_ring[KBD_RING_SIZE]; 
+static int kbd_ring_prod = 0;
+static int kbd_ring_cons = 0;
+
+#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1))
+#define KBD_RING_FULL    (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons)
+#define KBD_RING_EMPTY   (kbd_ring_prod == kbd_ring_cons)
+
+static void kbd_ring_push(unsigned char status, unsigned char scancode)
+{
+    if ( KBD_RING_FULL )
+        return;
+    
+    kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status);
+    kbd_ring_prod = KBD_RING_INC(kbd_ring_prod);
+}
+
+static int kbd_ring_pop(void)
+{
+    int ret;
+
+    if ( KBD_RING_EMPTY )
+    {
+        /* Read directly from controller - no events waiting in ring. */
+        unsigned char status = kbd_read_status();
+        unsigned char scancode = kbd_read_input(); 
+        ret = KBD_CODE(scancode, status);
+    }
+    else
+    {
+        ret = kbd_ring[kbd_ring_cons];
+        kbd_ring_cons = KBD_RING_INC(kbd_ring_cons);
+    }
+
+    return ret;
+}
+
+
+/*
+ * NB. Lock is essential as there are two distinct interrupts (keyboard + aux).
+ * Also interrupts may disturb guest OS actions.
+ */
+static spinlock_t kbd_lock;
+
+long do_kbd_op(unsigned char op, unsigned char val)
+{
+    unsigned long flags;
+    long ret = -EINVAL;
+
+    if ( !CONSOLE_ISOWNER(current) ) 
+        return -EPERM;  
+
+    spin_lock_irqsave(&kbd_lock, flags);
+
+    switch ( op )
+    {
+    case KBD_OP_WRITEOUTPUT:
+        kbd_write_output(val);
+        ret = 0L;
+        break;
+    case KBD_OP_WRITECOMMAND:
+        kbd_write_command(val);
+        ret = 0L;
+        break;
+    case KBD_OP_READ:
+        ret = kbd_ring_pop();
+        break;
+    }
+
+    spin_unlock_irqrestore(&kbd_lock, flags);
+
+    return ret;
+}
+
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+    unsigned char status=0, scancode;
+    unsigned int work = 1000;
+    unsigned long cpu_mask = 0, flags;
+    struct task_struct *p = CONSOLE_OWNER;
+
+    spin_lock_irqsave(&kbd_lock, flags);
+
+    while ( (--work > 0) && ((status = kbd_read_status()) & KBD_STAT_OBF) )
+    {
+        scancode = kbd_read_input();
+      
+#ifdef CONFIG_XEN_ATTENTION_KEY
+        if ( !(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF)) )
+        {
+            if ( (scancode & ~KBD_SCANCODE_KEYUP_MASK) == XEN_ATTENTION_KEY )
+            {
+                xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK);
+               continue;
+            } 
+            else if ( xen_attention_key_down )
+            {
+                key_handler *handler; 
+                unsigned char key;
+                spin_unlock_irqrestore(&kbd_lock, flags);
+                key = convert_scancode(scancode); 
+                if ( key && (handler = get_key_handler(key)) )
+                    (*handler)(key, dev_id, regs); 
+                spin_lock_irqsave(&kbd_lock, flags);
+                continue;
+            }
+        }
+#endif
+      
+        if ( p != NULL )
+        {
+            kbd_ring_push(status, scancode);
+            cpu_mask |= mark_guest_event(p, _EVENT_PS2);
+        }
+    }
+    
+    if ( !work )
+        printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status);
+
+    spin_unlock_irqrestore(&kbd_lock, flags);
+
+    if ( p != NULL )
+    {
+        put_task_struct(p);
+        guest_event_notify(cpu_mask);
+    }
+}
+    
+    
+
+void initialize_keyboard()
+{
+    spin_lock_init(&kbd_lock);
+
+    if( request_irq(KEYBOARD_IRQ, keyboard_interrupt, 
+                    SA_NOPROFILE, "keyboard", NULL)) 
+    {
+        printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); 
+        return;
+    }
+
+    if ( request_irq(AUX_IRQ, keyboard_interrupt, 
+                     SA_NOPROFILE, "PS/2 Mouse", NULL)) 
+    {
+        printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ); 
+        return;
+    }
+}
+
diff --git a/xen/drivers/char/xen_kbd.c b/xen/drivers/char/xen_kbd.c
deleted file mode 100644 (file)
index 4326050..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-#include <asm-i386/io.h>
-#include <asm-i386/irq.h>
-#include <xeno/sched.h>
-#include <xeno/keyhandler.h>  
-#include <hypervisor-ifs/kbd.h>
-#include <xeno/event.h>
-#include <xeno/console.h>
-
-/* Hash-defines torn from <linux/pc_keyb.h> and <asm/keyboard.h> */
-
-#define KBD_STATUS_REG      0x64 /* Status register (R) */
-#define KBD_CNTL_REG        0x64 /* Controller command register (W) */
-#define KBD_DATA_REG        0x60 /* Keyboard data register (R/W) */
-
-/* register status bits */
-#define KBD_STAT_OBF        0x01 /* Keyboard output buffer full */
-#define KBD_STAT_IBF        0x02 /* Keyboard input buffer full */
-#define KBD_STAT_SELFTEST    0x04 /* Self test successful */
-#define KBD_STAT_CMD        0x08 /* Last write was a command write (0=data) */
-
-#define KBD_STAT_UNLOCKED    0x10 /* Zero if keyboard locked */
-#define KBD_STAT_MOUSE_OBF   0x20 /* Mouse output buffer full */
-#define KBD_STAT_GTO        0x40 /* General receive/xmit timeout */
-#define KBD_STAT_PERR       0x80 /* Parity error */
-
-#define kbd_read_input() inb(KBD_DATA_REG)
-#define kbd_read_status() inb(KBD_STATUS_REG)
-
-#define KEYBOARD_IRQ  1
-#define AUX_IRQ      12
-
-#define kbd_write_output(val) outb(val, KBD_DATA_REG)
-#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
-
-#ifdef CONFIG_XEN_ATTENTION_KEY
-
-static int xen_attention_key_down = 0;
-#define XEN_ATTENTION_KEY 0x46 /* Scroll Lock */
-#define KBD_SCANCODE_KEYUP_MASK 0x80
-
-/* Simple scancode-to-key mappings for internal Xen use. */
-
-static unsigned char keymap_normal[] =
-{
-    0 , 0 ,'1','2', '3','4','5','6',    '7','8','9','0', '-','=','\b','\t',
-    'q','w','e','r', 't','y','u','i',    'o','p','[',']','\r', 0 ,'a','s',
-    'd','f','g','h', 'j','k','l',';',   '\'','`', 0 ,'#', 'z','x','c','v',
-    'b','n','m',',', '.','/', 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 ,'\\', 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 
-};
-
-static unsigned char keymap_shift[] =
-{
-    0 , 0 ,'!','"', '#','$','%','^',    '&','*','(',')', '_','+','\b','\t',
-    'Q','W','E','R', 'T','Y','U','I',    'O','P','{','}','\r', 0 ,'A','S',
-    'D','F','G','H', 'J','K','L',':',    '@', 0 , 0 ,'~', 'Z','X','C','V',
-    'B','N','M','<', '>','?', 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 ,'|', 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,
-    0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 ,     0 , 0 , 0 , 0 ,  0 , 0 , 0 , 0 
-};
-
-
-static int keyboard_shift = 0;
-
-static unsigned char convert_scancode (unsigned char scancode)
-{
-    unsigned char value = 0;
-
-    switch ( scancode ) 
-    {
-
-    case 0xaa: /* shift (left) UP */
-    case 0xb6: /* shift (right) UP */
-       keyboard_shift = 0;
-       break;
-
-    case 0x2a: /* shift (left) DOWN */
-    case 0x36: /* shift (right) DOWN */
-       keyboard_shift = 1;
-       break;
-
-    default:
-        /* Only process key-up events */
-        if(!(scancode & KBD_SCANCODE_KEYUP_MASK)) 
-            break; 
-       scancode = scancode & ~KBD_SCANCODE_KEYUP_MASK; 
-       if (keyboard_shift)
-           value = keymap_shift[scancode];
-       else
-           value = keymap_normal[scancode];
-        break;
-    }
-
-    return value;
-}
-
-#endif /* CONFIG_XEN_ATTENTION_KEY */
-
-
-/* We store kbd events awaiting receive by a guest OS in a ring buffer. */
-#define KBD_RING_SIZE 64 
-static int kbd_ring[KBD_RING_SIZE]; 
-static int kbd_ring_prod = 0;
-static int kbd_ring_cons = 0;
-
-#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1))
-#define KBD_RING_FULL    (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons)
-#define KBD_RING_EMPTY   (kbd_ring_prod == kbd_ring_cons)
-
-static void kbd_ring_push(unsigned char status, unsigned char scancode)
-{
-    if ( KBD_RING_FULL )
-        return;
-    
-    kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status);
-    kbd_ring_prod = KBD_RING_INC(kbd_ring_prod);
-}
-
-static int kbd_ring_pop(void)
-{
-    int ret;
-
-    if ( KBD_RING_EMPTY )
-    {
-        /* Read directly from controller - no events waiting in ring. */
-        unsigned char status = kbd_read_status();
-        unsigned char scancode = kbd_read_input(); 
-        ret = KBD_CODE(scancode, status);
-    }
-    else
-    {
-        ret = kbd_ring[kbd_ring_cons];
-        kbd_ring_cons = KBD_RING_INC(kbd_ring_cons);
-    }
-
-    return ret;
-}
-
-
-/*
- * NB. Lock is essential as there are two distinct interrupts (keyboard + aux).
- * Also interrupts may disturb guest OS actions.
- */
-static spinlock_t kbd_lock;
-
-long do_kbd_op(unsigned char op, unsigned char val)
-{
-    unsigned long flags;
-    long ret = -EINVAL;
-
-    if ( !CONSOLE_ISOWNER(current) ) 
-        return -EPERM;  
-
-    spin_lock_irqsave(&kbd_lock, flags);
-
-    switch ( op )
-    {
-    case KBD_OP_WRITEOUTPUT:
-        kbd_write_output(val);
-        ret = 0L;
-        break;
-    case KBD_OP_WRITECOMMAND:
-        kbd_write_command(val);
-        ret = 0L;
-        break;
-    case KBD_OP_READ:
-        ret = kbd_ring_pop();
-        break;
-    }
-
-    spin_unlock_irqrestore(&kbd_lock, flags);
-
-    return ret;
-}
-
-
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-    unsigned char status=0, scancode;
-    unsigned int work = 1000;
-    unsigned long cpu_mask = 0, flags;
-    struct task_struct *p = CONSOLE_OWNER;
-
-    spin_lock_irqsave(&kbd_lock, flags);
-
-    while ( (--work > 0) && ((status = kbd_read_status()) & KBD_STAT_OBF) )
-    {
-        scancode = kbd_read_input();
-      
-#ifdef CONFIG_XEN_ATTENTION_KEY
-        if ( !(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF)) )
-        {
-            if ( (scancode & ~KBD_SCANCODE_KEYUP_MASK) == XEN_ATTENTION_KEY )
-            {
-                xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK);
-               continue;
-            } 
-            else if ( xen_attention_key_down )
-            {
-                key_handler *handler; 
-                unsigned char key;
-                spin_unlock_irqrestore(&kbd_lock, flags);
-                key = convert_scancode(scancode); 
-                if ( key && (handler = get_key_handler(key)) )
-                    (*handler)(key, dev_id, regs); 
-                spin_lock_irqsave(&kbd_lock, flags);
-                continue;
-            }
-        }
-#endif
-      
-        if ( p != NULL )
-        {
-            kbd_ring_push(status, scancode);
-            cpu_mask |= mark_guest_event(p, _EVENT_PS2);
-        }
-    }
-    
-    if ( !work )
-        printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status);
-
-    spin_unlock_irqrestore(&kbd_lock, flags);
-
-    if ( p != NULL )
-    {
-        put_task_struct(p);
-        guest_event_notify(cpu_mask);
-    }
-}
-    
-    
-
-void initialize_keyboard()
-{
-    spin_lock_init(&kbd_lock);
-
-    if( request_irq(KEYBOARD_IRQ, keyboard_interrupt, 
-                    SA_NOPROFILE, "keyboard", NULL)) 
-    {
-        printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); 
-        return;
-    }
-
-    if ( request_irq(AUX_IRQ, keyboard_interrupt, 
-                     SA_NOPROFILE, "PS/2 Mouse", NULL)) 
-    {
-        printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ); 
-        return;
-    }
-}
-
index 3506932eafb8d25cc6e66b5903daa231623b85b8..ee950c01e1f550be125f5f6729b57a02f85ab58d 100644 (file)
@@ -42,7 +42,7 @@
 /* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
 #define __HYPERVISOR_set_trap_table        0
 #define __HYPERVISOR_mmu_update            1
-#define __HYPERVISOR_console_write         2
+#define __HYPERVISOR_console_write         2 /* DEPRECATED */
 #define __HYPERVISOR_set_gdt               3
 #define __HYPERVISOR_stack_switch          4
 #define __HYPERVISOR_set_callbacks         5
@@ -63,6 +63,7 @@
 #define __HYPERVISOR_set_timer_op         20
 #define __HYPERVISOR_event_channel_op     21
 #define __HYPERVISOR_xen_version          22
+#define __HYPERVISOR_serial_io            23
 
 /* And the trap vector is... */
 #define TRAP_INSTR "int $0x82"
 #define _EVENT_STOP     6
 #define _EVENT_EVTCHN   7
 #define _EVENT_VBD_UPD  8
+#define _EVENT_CONSOLE  9 /* This is only for domain-0 initial console. */
 
 /*
  * Virtual addresses beyond this are not modifiable by guest OSes. The 
 #define SCHEDOP_exit            3   /* Exit and kill this domain.        */
 #define SCHEDOP_stop            4   /* Stop executing this domain.       */
 
+/*
+ * Commands to HYPERVISOR_serial_io().
+ */
+#define SERIALIO_write          0
+#define SERIALIO_read           1
 
 #ifndef __ASSEMBLY__
 
index d68aa893bbf1c14506e6dbfcbe9dd3e778cb16e9..212199d9a506f52d489e803888b25d240534d69f 100644 (file)
@@ -9,28 +9,23 @@
 #ifndef __CONSOLE_H__
 #define __CONSOLE_H__
 
+#include <xeno/spinlock.h>
+
+extern spinlock_t console_lock;
+
 /*
  * Ownership of console --- currently hardwired to dom0. This is used to see 
  * who gets the PS/2 keyboard/mouse events
  */
-
-extern int sercon_handle;
-extern int vgacon_enabled;
-
 #define CONSOLE_ISOWNER(p) (p->domain == 0) 
 #define CONSOLE_OWNER      (find_domain_by_id(0))
 
-#define CONSOLE_RING_SIZE      16392
-#define CONSOLE_RING_CLEAR     1
-
-typedef struct console_ring_st
-{
-    char buf[CONSOLE_RING_SIZE];
-    unsigned int len;
-} console_ring_t;
-
-extern console_ring_t console_ring;
+void set_printk_prefix(const char *prefix);
 
+#define CONSOLE_RING_CLEAR 1
 long read_console_ring(unsigned long, unsigned int, unsigned int);
 
+void init_console(void);
+void console_endboot(int disable_vga);
+
 #endif
index 7aaac28bca36927a8fd8c4c7062513813502a8a1..21149a0f9ea1cdc146ce33ed2ec52fc9513ed173 100644 (file)
@@ -80,22 +80,14 @@ static void nonpriv_conwrite(const char *s, unsigned int count)
 
 static void priv_conwrite(const char *s, unsigned int count)
 {
-    static char str[256];
-    static int pos = 0;
-    int len;
+    int rc;
 
-    /* We buffer output until we see a newline, or until the buffer is full. */
-    while ( count != 0 )
+    while ( count > 0 )
     {
-        len = ((sizeof(str) - pos) > count) ? count : sizeof(str) - pos;
-        memcpy(str + pos, s, len);
-        pos   += len;
-        s     += len;
-        count -= len;
-        if ( (pos == sizeof(str)) || (str[pos-1] == '\n') )
+        if ( (rc = HYPERVISOR_serial_io(SERIALIO_write, count, s)) > 0 )
         {
-            (void)HYPERVISOR_console_write(str, pos);
-            pos = 0;
+            count -= rc;
+            s += rc;
         }
     }
 }
index bce5b9c24d7a7ac531f3090f2a80bef9427ca703..c6959e107b93083dc40f9e3fcb7e257c6af6ea6a 100644 (file)
@@ -156,7 +156,6 @@ static inline int HYPERVISOR_set_trap_table(trap_info_t *table)
     return ret;
 }
 
-
 static inline int HYPERVISOR_mmu_update(mmu_update_t *req, int count)
 {
     int ret;
@@ -175,19 +174,6 @@ static inline int HYPERVISOR_mmu_update(mmu_update_t *req, int count)
     return ret;
 }
 
-
-static inline int HYPERVISOR_console_write(const char *str, int count)
-{
-    int ret;
-    __asm__ __volatile__ (
-        TRAP_INSTR
-        : "=a" (ret) : "0" (__HYPERVISOR_console_write), 
-        "b" (str), "c" (count) : "memory" );
-
-
-    return ret;
-}
-
 static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
 {
     int ret;
@@ -454,4 +440,15 @@ static inline int HYPERVISOR_xen_version(int cmd)
     return ret;
 }
 
+static inline int HYPERVISOR_serial_io(int cmd, int count, char *str)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_serial_io),
+        "b" (cmd), "c" (count), "d" (str) : "memory" );
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */
index 33bdbd7817f837a88e5597c360c866385209da8d..2b290252be18c673dffc4c404929323d0fb6e7af 100644 (file)
@@ -188,12 +188,12 @@ extern unsigned long mmu_cr4_features;
 
 static inline void set_in_cr4 (unsigned long mask)
 {
-    HYPERVISOR_console_write("No set_in_cr4", 13);
+    BUG();
 }
 
 static inline void clear_in_cr4 (unsigned long mask)
 {
-    HYPERVISOR_console_write("No clear_in_cr4", 15);
+    BUG();
 }
 
 /*
index 6ab619a6074ed3ce43b0ba9bd16e9bf257cc4767..284bd434a33625875e13452a74a9a2d0a9d19561 100644 (file)
@@ -110,7 +110,6 @@ NORET_TYPE void panic(const char * fmt, ...)
 #endif
                CHECK_EMERGENCY_SYNC
 #if defined(CONFIG_XENO)
-               HYPERVISOR_console_write(buf, strlen(buf));
                HYPERVISOR_exit();
 #endif
        }
diff --git a/xenolinux-2.4.25-sparse/kernel/printk.c b/xenolinux-2.4.25-sparse/kernel/printk.c
deleted file mode 100644 (file)
index 6cfedd9..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- *  linux/kernel/printk.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * Modified to make sys_syslog() more flexible: added commands to
- * return the last 4k of kernel messages, regardless of whether
- * they've been read or not.  Added option to suppress kernel printk's
- * to the console.  Added hook for sending the console messages
- * elsewhere, in preparation for a serial line console (someday).
- * Ted Ts'o, 2/11/93.
- * Modified for sysctl support, 1/8/97, Chris Horn.
- * Fixed SMP synchronization, 08/08/99, Manfred Spraul 
- *     manfreds@colorfullife.com
- * Rewrote bits to get rid of console_lock
- *     01Mar01 Andrew Morton <andrewm@uow.edu.au>
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/smp_lock.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>                   /* For in_interrupt() */
-#include <linux/config.h>
-
-#include <asm/uaccess.h>
-
-#if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
-#if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
-#define LOG_BUF_LEN    (65536)
-#elif defined(CONFIG_ARCH_S390)
-#define LOG_BUF_LEN    (131072)
-#elif defined(CONFIG_SMP)
-#define LOG_BUF_LEN    (32768)
-#else  
-#define LOG_BUF_LEN    (16384)                 /* This must be a power of two */
-#endif
-#else /* CONFIG_LOG_BUF_SHIFT */
-#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
-#endif
-
-#define LOG_BUF_MASK   (LOG_BUF_LEN-1)
-
-#ifndef arch_consoles_callable
-#define arch_consoles_callable() (1)
-#endif
-
-/* printk's without a loglevel use this.. */
-#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
-
-/* We show everything that is MORE important than this.. */
-#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
-#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
-
-DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
-int console_printk[4] = {
-       DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
-       DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
-       MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
-       DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
-};
-
-int oops_in_progress;
-
-/*
- * console_sem protects the console_drivers list, and also
- * provides serialisation for access to the entire console
- * driver system.
- */
-static DECLARE_MUTEX(console_sem);
-struct console *console_drivers;
-
-/*
- * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
- * It is also used in interesting ways to provide interlocking in
- * release_console_sem().
- */
-static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
-
-static char log_buf[LOG_BUF_LEN];
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-/*
- * The indices into log_buf are not constrained to LOG_BUF_LEN - they
- * must be masked before subscripting
- */
-static unsigned long log_start;                        /* Index into log_buf: next char to be read by syslog() */
-static unsigned long con_start;                        /* Index into log_buf: next char to be sent to consoles */
-static unsigned long log_end;                  /* Index into log_buf: most-recently-written-char + 1 */
-static unsigned long logged_chars;             /* Number of chars produced since last read+clear operation */
-
-struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
-static int preferred_console = -1;
-
-/* Flag: console code may call schedule() */
-static int console_may_schedule;
-
-/*
- *     Setup a list of consoles. Called from init/main.c
- */
-static int __init console_setup(char *str)
-{
-       struct console_cmdline *c;
-       char name[sizeof(c->name)];
-       char *s, *options;
-       int i, idx;
-
-       /*
-        *      Decode str into name, index, options.
-        */
-       if (str[0] >= '0' && str[0] <= '9') {
-               strcpy(name, "ttyS");
-               strncpy(name + 4, str, sizeof(name) - 5);
-       } else
-               strncpy(name, str, sizeof(name) - 1);
-       name[sizeof(name) - 1] = 0;
-       if ((options = strchr(str, ',')) != NULL)
-               *(options++) = 0;
-#ifdef __sparc__
-       if (!strcmp(str, "ttya"))
-               strcpy(name, "ttyS0");
-       if (!strcmp(str, "ttyb"))
-               strcpy(name, "ttyS1");
-#endif
-       for(s = name; *s; s++)
-               if (*s >= '0' && *s <= '9')
-                       break;
-       idx = simple_strtoul(s, NULL, 10);
-       *s = 0;
-
-       /*
-        *      See if this tty is not yet registered, and
-        *      if we have a slot free.
-        */
-       for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
-               if (strcmp(console_cmdline[i].name, name) == 0 &&
-                         console_cmdline[i].index == idx) {
-                               preferred_console = i;
-                               return 1;
-               }
-       if (i == MAX_CMDLINECONSOLES)
-               return 1;
-       preferred_console = i;
-       c = &console_cmdline[i];
-       memcpy(c->name, name, sizeof(c->name));
-       c->options = options;
-       c->index = idx;
-       return 1;
-}
-
-__setup("console=", console_setup);
-
-/*
- * Commands to do_syslog:
- *
- *     0 -- Close the log.  Currently a NOP.
- *     1 -- Open the log. Currently a NOP.
- *     2 -- Read from the log.
- *     3 -- Read all messages remaining in the ring buffer.
- *     4 -- Read and clear all messages remaining in the ring buffer
- *     5 -- Clear ring buffer.
- *     6 -- Disable printk's to console
- *     7 -- Enable printk's to console
- *     8 -- Set level of messages printed to console
- *     9 -- Return number of unread characters in the log buffer
- */
-int do_syslog(int type, char * buf, int len)
-{
-       unsigned long i, j, limit, count;
-       int do_clear = 0;
-       char c;
-       int error = 0;
-
-       switch (type) {
-       case 0:         /* Close log */
-               break;
-       case 1:         /* Open log */
-               break;
-       case 2:         /* Read from log */
-               error = -EINVAL;
-               if (!buf || len < 0)
-                       goto out;
-               error = 0;
-               if (!len)
-                       goto out;
-               error = verify_area(VERIFY_WRITE,buf,len);
-               if (error)
-                       goto out;
-               error = wait_event_interruptible(log_wait, (log_start - log_end));
-               if (error)
-                       goto out;
-               i = 0;
-               spin_lock_irq(&logbuf_lock);
-               while ((log_start != log_end) && i < len) {
-                       c = LOG_BUF(log_start);
-                       log_start++;
-                       spin_unlock_irq(&logbuf_lock);
-                       __put_user(c,buf);
-                       buf++;
-                       i++;
-                       spin_lock_irq(&logbuf_lock);
-               }
-               spin_unlock_irq(&logbuf_lock);
-               error = i;
-               break;
-       case 4:         /* Read/clear last kernel messages */
-               do_clear = 1; 
-               /* FALL THRU */
-       case 3:         /* Read last kernel messages */
-               error = -EINVAL;
-               if (!buf || len < 0)
-                       goto out;
-               error = 0;
-               if (!len)
-                       goto out;
-               error = verify_area(VERIFY_WRITE,buf,len);
-               if (error)
-                       goto out;
-               count = len;
-               if (count > LOG_BUF_LEN)
-                       count = LOG_BUF_LEN;
-               spin_lock_irq(&logbuf_lock);
-               if (count > logged_chars)
-                       count = logged_chars;
-               if (do_clear)
-                       logged_chars = 0;
-               limit = log_end;
-               /*
-                * __put_user() could sleep, and while we sleep
-                * printk() could overwrite the messages 
-                * we try to copy to user space. Therefore
-                * the messages are copied in reverse. <manfreds>
-                */
-               for(i=0;i < count;i++) {
-                       j = limit-1-i;
-                       if (j+LOG_BUF_LEN < log_end)
-                               break;
-                       c = LOG_BUF(j);
-                       spin_unlock_irq(&logbuf_lock);
-                       __put_user(c,&buf[count-1-i]);
-                       spin_lock_irq(&logbuf_lock);
-               }
-               spin_unlock_irq(&logbuf_lock);
-               error = i;
-               if(i != count) {
-                       int offset = count-error;
-                       /* buffer overflow during copy, correct user buffer. */
-                       for(i=0;i<error;i++) {
-                               __get_user(c,&buf[i+offset]);
-                               __put_user(c,&buf[i]);
-                       }
-               }
-
-               break;
-       case 5:         /* Clear ring buffer */
-               spin_lock_irq(&logbuf_lock);
-               logged_chars = 0;
-               spin_unlock_irq(&logbuf_lock);
-               break;
-       case 6:         /* Disable logging to console */
-               spin_lock_irq(&logbuf_lock);
-               console_loglevel = minimum_console_loglevel;
-               spin_unlock_irq(&logbuf_lock);
-               break;
-       case 7:         /* Enable logging to console */
-               spin_lock_irq(&logbuf_lock);
-               console_loglevel = default_console_loglevel;
-               spin_unlock_irq(&logbuf_lock);
-               break;
-       case 8:         /* Set level of messages printed to console */
-               error = -EINVAL;
-               if (len < 1 || len > 8)
-                       goto out;
-               if (len < minimum_console_loglevel)
-                       len = minimum_console_loglevel;
-               spin_lock_irq(&logbuf_lock);
-               console_loglevel = len;
-               spin_unlock_irq(&logbuf_lock);
-               error = 0;
-               break;
-       case 9:         /* Number of chars in the log buffer */
-               spin_lock_irq(&logbuf_lock);
-               error = log_end - log_start;
-               spin_unlock_irq(&logbuf_lock);
-               break;
-       default:
-               error = -EINVAL;
-               break;
-       }
-out:
-       return error;
-}
-
-asmlinkage long sys_syslog(int type, char * buf, int len)
-{
-       if ((type != 3) && !capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       return do_syslog(type, buf, len);
-}
-
-/*
- * Call the console drivers on a range of log_buf
- */
-static void __call_console_drivers(unsigned long start, unsigned long end)
-{
-       struct console *con;
-
-       for (con = console_drivers; con; con = con->next) {
-               if ((con->flags & CON_ENABLED) && con->write)
-                       con->write(con, &LOG_BUF(start), end - start);
-       }
-}
-
-/*
- * Write out chars from start to end - 1 inclusive
- */
-static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
-{
-       if (msg_log_level < console_loglevel && console_drivers && start != end) {
-               if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
-                       /* wrapped write */
-                       __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
-                       __call_console_drivers(0, end & LOG_BUF_MASK);
-               } else {
-                       __call_console_drivers(start, end);
-               }
-       }
-}
-
-/*
- * Call the console drivers, asking them to write out
- * log_buf[start] to log_buf[end - 1].
- * The console_sem must be held.
- */
-static void call_console_drivers(unsigned long start, unsigned long end)
-{
-       unsigned long cur_index, start_print;
-       static int msg_level = -1;
-
-       if (((long)(start - end)) > 0)
-               BUG();
-
-       cur_index = start;
-       start_print = start;
-       while (cur_index != end) {
-               if (    msg_level < 0 &&
-                       ((end - cur_index) > 2) &&
-                       LOG_BUF(cur_index + 0) == '<' &&
-                       LOG_BUF(cur_index + 1) >= '0' &&
-                       LOG_BUF(cur_index + 1) <= '7' &&
-                       LOG_BUF(cur_index + 2) == '>')
-               {
-                       msg_level = LOG_BUF(cur_index + 1) - '0';
-                       cur_index += 3;
-                       start_print = cur_index;
-               }
-               while (cur_index != end) {
-                       char c = LOG_BUF(cur_index);
-                       cur_index++;
-
-                       if (c == '\n') {
-                               if (msg_level < 0) {
-                                       /*
-                                        * printk() has already given us loglevel tags in
-                                        * the buffer.  This code is here in case the
-                                        * log buffer has wrapped right round and scribbled
-                                        * on those tags
-                                        */
-                                       msg_level = default_message_loglevel;
-                               }
-                               _call_console_drivers(start_print, cur_index, msg_level);
-                               msg_level = -1;
-                               start_print = cur_index;
-                               break;
-                       }
-               }
-       }
-       _call_console_drivers(start_print, end, msg_level);
-}
-
-static void emit_log_char(char c)
-{
-       LOG_BUF(log_end) = c;
-       log_end++;
-       if (log_end - log_start > LOG_BUF_LEN)
-               log_start = log_end - LOG_BUF_LEN;
-       if (log_end - con_start > LOG_BUF_LEN)
-               con_start = log_end - LOG_BUF_LEN;
-       if (logged_chars < LOG_BUF_LEN)
-               logged_chars++;
-}
-
-/*
- * This is printk.  It can be called from any context.  We want it to work.
- * 
- * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
- * call the console drivers.  If we fail to get the semaphore we place the output
- * into the log buffer and return.  The current holder of the console_sem will
- * notice the new output in release_console_sem() and will send it to the
- * consoles before releasing the semaphore.
- *
- * One effect of this deferred printing is that code which calls printk() and
- * then changes console_loglevel may break. This is because console_loglevel
- * is inspected when the actual printing occurs.
- */
-asmlinkage int printk(const char *fmt, ...)
-{
-       va_list args;
-       unsigned long flags;
-       int printed_len;
-       char *p;
-       static char printk_buf[1024];
-       static int log_level_unknown = 1;
-
-       if (oops_in_progress) {
-               /* If a crash is occurring, make sure we can't deadlock */
-               spin_lock_init(&logbuf_lock);
-               /* And make sure that we print immediately */
-               init_MUTEX(&console_sem);
-       }
-
-       /* This stops the holder of console_sem just where we want him */
-       spin_lock_irqsave(&logbuf_lock, flags);
-
-       /* Emit the output into the temporary buffer */
-       va_start(args, fmt);
-       printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
-       va_end(args);
-
-#if 0
-       /* Useful if things are going wrong very early in the day. */
-       (void)HYPERVISOR_console_write(printk_buf, printed_len);
-#endif
-
-       /*
-        * Copy the output into log_buf.  If the caller didn't provide
-        * appropriate log level tags, we insert them here
-        */
-       for (p = printk_buf; *p; p++) {
-               if (log_level_unknown) {
-                       if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
-                               emit_log_char('<');
-                               emit_log_char(default_message_loglevel + '0');
-                               emit_log_char('>');
-                       }
-                       log_level_unknown = 0;
-               }
-               emit_log_char(*p);
-               if (*p == '\n')
-                       log_level_unknown = 1;
-       }
-
-       if (!arch_consoles_callable()) {
-               /*
-                * On some architectures, the consoles are not usable
-                * on secondary CPUs early in the boot process.
-                */
-               spin_unlock_irqrestore(&logbuf_lock, flags);
-               goto out;
-       }
-       if (!down_trylock(&console_sem)) {
-               /*
-                * We own the drivers.  We can drop the spinlock and let
-                * release_console_sem() print the text
-                */
-               spin_unlock_irqrestore(&logbuf_lock, flags);
-               console_may_schedule = 0;
-               release_console_sem();
-       } else {
-               /*
-                * Someone else owns the drivers.  We drop the spinlock, which
-                * allows the semaphore holder to proceed and to call the
-                * console drivers with the output which we just produced.
-                */
-               spin_unlock_irqrestore(&logbuf_lock, flags);
-       }
-out:
-       return printed_len;
-}
-EXPORT_SYMBOL(printk);
-
-/**
- * acquire_console_sem - lock the console system for exclusive use.
- *
- * Acquires a semaphore which guarantees that the caller has
- * exclusive access to the console system and the console_drivers list.
- *
- * Can sleep, returns nothing.
- */
-void acquire_console_sem(void)
-{
-       if (in_interrupt())
-               BUG();
-       down(&console_sem);
-       console_may_schedule = 1;
-}
-EXPORT_SYMBOL(acquire_console_sem);
-
-/**
- * release_console_sem - unlock the console system
- *
- * Releases the semaphore which the caller holds on the console system
- * and the console driver list.
- *
- * While the semaphore was held, console output may have been buffered
- * by printk().  If this is the case, release_console_sem() emits
- * the output prior to releasing the semaphore.
- *
- * If there is output waiting for klogd, we wake it up.
- *
- * release_console_sem() may be called from any context.
- */
-void release_console_sem(void)
-{
-       unsigned long flags;
-       unsigned long _con_start, _log_end;
-       unsigned long must_wake_klogd = 0;
-
-       for ( ; ; ) {
-               spin_lock_irqsave(&logbuf_lock, flags);
-               must_wake_klogd |= log_start - log_end;
-               if (con_start == log_end)
-                       break;                  /* Nothing to print */
-               _con_start = con_start;
-               _log_end = log_end;
-               con_start = log_end;            /* Flush */
-               spin_unlock_irqrestore(&logbuf_lock, flags);
-               call_console_drivers(_con_start, _log_end);
-       }
-       console_may_schedule = 0;
-       up(&console_sem);
-       spin_unlock_irqrestore(&logbuf_lock, flags);
-       if (must_wake_klogd && !oops_in_progress)
-               wake_up_interruptible(&log_wait);
-}
-
-/** console_conditional_schedule - yield the CPU if required
- *
- * If the console code is currently allowed to sleep, and
- * if this CPU should yield the CPU to another task, do
- * so here.
- *
- * Must be called within acquire_console_sem().
- */
-void console_conditional_schedule(void)
-{
-       if (console_may_schedule && current->need_resched) {
-               set_current_state(TASK_RUNNING);
-               schedule();
-       }
-}
-
-void console_print(const char *s)
-{
-       printk(KERN_EMERG "%s", s);
-}
-EXPORT_SYMBOL(console_print);
-
-void console_unblank(void)
-{
-       struct console *c;
-
-       /*
-        * Try to get the console semaphore. If someone else owns it
-        * we have to return without unblanking because console_unblank
-        * may be called in interrupt context.
-        */
-       if (down_trylock(&console_sem) != 0)
-               return;
-       console_may_schedule = 0;
-       for (c = console_drivers; c != NULL; c = c->next)
-               if ((c->flags & CON_ENABLED) && c->unblank)
-                       c->unblank();
-       release_console_sem();
-}
-EXPORT_SYMBOL(console_unblank);
-
-/*
- * The console driver calls this routine during kernel initialization
- * to register the console printing procedure with printk() and to
- * print any messages that were printed by the kernel before the
- * console driver was initialized.
- */
-void register_console(struct console * console)
-{
-       int     i;
-       unsigned long flags;
-
-       /*
-        *      See if we want to use this console driver. If we
-        *      didn't select a console we take the first one
-        *      that registers here.
-        */
-       if (preferred_console < 0) {
-               if (console->index < 0)
-                       console->index = 0;
-               if (console->setup == NULL ||
-                   console->setup(console, NULL) == 0) {
-                       console->flags |= CON_ENABLED | CON_CONSDEV;
-                       preferred_console = 0;
-               }
-       }
-
-       /*
-        *      See if this console matches one we selected on
-        *      the command line.
-        */
-       for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
-               if (strcmp(console_cmdline[i].name, console->name) != 0)
-                       continue;
-               if (console->index >= 0 &&
-                   console->index != console_cmdline[i].index)
-                       continue;
-               if (console->index < 0)
-                       console->index = console_cmdline[i].index;
-               if (console->setup &&
-                   console->setup(console, console_cmdline[i].options) != 0)
-                       break;
-               console->flags |= CON_ENABLED;
-               console->index = console_cmdline[i].index;
-               if (i == preferred_console)
-                       console->flags |= CON_CONSDEV;
-               break;
-       }
-
-       if (!(console->flags & CON_ENABLED))
-               return;
-
-       /*
-        *      Put this console in the list - keep the
-        *      preferred driver at the head of the list.
-        */
-       acquire_console_sem();
-       if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
-               console->next = console_drivers;
-               console_drivers = console;
-       } else {
-               console->next = console_drivers->next;
-               console_drivers->next = console;
-       }
-       if (console->flags & CON_PRINTBUFFER) {
-               /*
-                * release_console_sem() will print out the buffered messages for us.
-                */
-               spin_lock_irqsave(&logbuf_lock, flags);
-               con_start = log_start;
-               spin_unlock_irqrestore(&logbuf_lock, flags);
-       }
-       release_console_sem();
-}
-EXPORT_SYMBOL(register_console);
-
-int unregister_console(struct console * console)
-{
-        struct console *a,*b;
-       int res = 1;
-
-       acquire_console_sem();
-       if (console_drivers == console) {
-               console_drivers=console->next;
-               res = 0;
-       } else {
-               for (a=console_drivers->next, b=console_drivers ;
-                    a; b=a, a=b->next) {
-                       if (a == console) {
-                               b->next = a->next;
-                               res = 0;
-                               break;
-                       }  
-               }
-       }
-       
-       /* If last console is removed, we re-enable picking the first
-        * one that gets registered. Without that, pmac early boot console
-        * would prevent fbcon from taking over.
-        */
-       if (console_drivers == NULL)
-               preferred_console = -1;
-               
-
-       release_console_sem();
-       return res;
-}
-EXPORT_SYMBOL(unregister_console);
-       
-/**
- * tty_write_message - write a message to a certain tty, not just the console.
- *
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
- */
-void tty_write_message(struct tty_struct *tty, char *msg)
-{
-       if (tty && tty->driver.write)
-               tty->driver.write(tty, 0, msg, strlen(msg));
-       return;
-}